import Vue from "vue"
import { canvasId } from "./const"
import store from "@/store"

/** *
 * 深拷贝
//  */
// export function deepCopy(data, hash = new WeakMap()) {
//   if(typeof data !== "object" || data === null){
//         throw new TypeError("传入参数不是对象");
//     }
//   // 判断传入的待拷贝对象的引用是否存在于hash中
//   if(hash.has(data)) {
//         return hash.get(data);
//     }
//   const newData = {};
//   const dataKeys = Object.keys(data);
//   dataKeys.forEach(value => {
//      const currentDataValue = data[value];
//      // 基本数据类型的值和函数直接赋值拷贝
//      if (typeof currentDataValue !== "object" || currentDataValue === null) {
//           newData[value] = currentDataValue;
//       } else if (Array.isArray(currentDataValue)) {
//          // 实现数组的深拷贝
//         newData[value] = [...currentDataValue];
//       } else if (currentDataValue instanceof Set) {
//          // 实现set数据的深拷贝
//          newData[value] = new Set([...currentDataValue]);
//       } else if (currentDataValue instanceof Map) {
//          // 实现map数据的深拷贝
//          newData[value] = new Map([...currentDataValue]);
//       } else {
//          // 将这个待拷贝对象的引用存于hash中
//          hash.set(data,data);
//          // 普通对象则递归赋值
//          newData[value] = deepCopy(currentDataValue, hash);
//       }
//    });
//   return newData;
// }

/**
 * 深拷贝
 * @param { object } target
 * @returns { object }
 */
export function deepCopy(target) {
  if (typeof target === "object") {
      const result = Array.isArray(target) ? [] : {}
      for (const key in target) {
          if (typeof target[key] === "object") {
              result[key] = deepCopy(target[key])
          } else {
              result[key] = target[key]
          }
      }

      return result
  }

  return target
}

/**
 * 交换数组元素
 * @param { [] } arr
 * @param { number } i
 * @param { number } j
 */
 export function swap(arr, i, j) {
  const temp = arr[i]
  Vue.set(arr, i, arr[j])
  Vue.set(arr, j, temp)
}

/**
 * 根据选择器获取dom
 * @param { string } selector
 * @returns
 */
export function $(selector) {
  return document.querySelector(selector)
}

/**
 * 判断两个对象的属性是否相同
 * @param { object } obj1
 * @param { object } obj2
 * @returns { boolean }
 */
export function diffObject(obj1,obj2){
  const o1 = obj1 instanceof Object
  const o2 = obj2 instanceof Object
  // 判断是不是对象
  if (!o1 || !o2) {
    return obj1 === obj2
  }

  // Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,
  // 例如：数组返回下表：let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2;
  if (Object.keys(obj1).length !== Object.keys(obj2).length) {
      return false
  }

  for (const o in obj1) {
      const t1 = obj1[o] instanceof Object
      const t2 = obj2[o] instanceof Object
      if (t1 && t2) {
          return diffObject(obj1[o], obj2[o])
      } if (obj1[o] !== obj2[o]) {
          return false
      }
  }
  return true
}

/**
 * 获取两点之间的距离
 * @param {*} p1
 * @param {*} p2
 * @returns
 */
export function getDistance(p1, p2){
  const dx = Math.abs(p2.clientX - p1.clientX)
  const dy = Math.abs(p2.clientY - p1.clientY)
  return Math.sqrt(dx ** 2 + dy ** 2)
}


/**
 * 解析json字符串为对象,修复丢失function的bug
 * @param { string } str
 * @returns
 */
export function parse(str){
  return JSON.parse(str,function(k,v){
    if (v?.indexOf && v.indexOf('function') > -1){
      return eval("(function(){return " + v + " })()")
    }
    return v
  })
}

/**
 * 将对象转换为json字符串,修复丢失function的bug
 * @param {*} obj
 * @returns
 */
export function stringify(obj){
  return JSON.stringify(obj, function(key, val) {
    if (typeof val === 'function') {
      return val + ''
    }
    return val
  })
}

/**
 * 遍历数组,并被每个元素执行回调
 * @param {*} list
 * @param {*} callback
 * @param {boolean} isErgodicShow 是否只遍历可见(即当前tab下)的组件
 */
export function ergodicList(list,callback = () => {}, isErgodicShow){
  list.forEach(element => {
    callback(element)
    if (element.props.list){
      if (isErgodicShow){
        const tabItem = element.props.list.find(tab => tab.value === element.props.value)
        tabItem && ergodicList(tabItem.children, callback)
      }
      else {
        element.props.list.forEach(item => {
          item.children && ergodicList(item.children, callback)
        })
      }
    }
  })
}

/**
 * 根据id获取组件
 * @param { Component[] } list
 * @param { Key } key
 * @returns
 */
export function getComponentByKey(list, key){
  const componentList = getComponentListByKeys(list, [key])
  if (componentList.length > 0){
    return componentList[0]
  }
  else {
    return null
  }
}


/**
 * 根据ids获取组件列表
 * @param { Component[] } componentList
 * @param { Key[] } keys
 * @returns
 */
export function getComponentListByKeys(componentList, keys){
  const filterList = []
  const each = (list, keys) => {
    for (let i = 0; i < list.length; i++){
      const item = list[i]
      if (keys.includes(item.key)){
        filterList.push(item)
      } else {
        if (item.props.list){
          for (let j = 0; j < item.props.list.length; j++){
            each(item.props.list[j].children,keys, filterList)
          }
        }
      }
    }
  }
  each(componentList, keys)
  return filterList
}

/**
 * 根据types获取组件列表
 * @param { Component[] } componentList
 * @param { string[] } types
 * @returns { Component[] }
 */
 export function getComponentListByTypes(componentList, types){
  const filterList = []
  const each = (list, types) => {
    for (let i = 0; i < list.length; i++){
      const item = list[i]
      if (types.includes(item.type)){
        filterList.push(item)
      } else {
        if (item.props.list){
          for (let j = 0; j < item.props.list.length; j++){
            each(item.props.list[j].children,types, filterList)
          }
        }
      }
    }
  }
  each(componentList, types)
  return filterList
}

/**
 * 递归删除数组某一项
 * @param { [] } treeData
 * @param { Key } key
 */
export function removeComponentByKey(treeData,key) {
  for (let i = treeData.length; i > 0; i--){
    if (treeData[i - 1].key === key){
      treeData.splice(i - 1,1)
    } else {
      if (treeData[i - 1].props.list){
        treeData[i - 1].props.list.forEach(item => {
          item.children && removeComponentByKey(item.children,key)
        })
      }
    }
  }
}

/**
 * 根据key的数组递归删除数组元素
 * @param { [] } treeData
 * @param { Key[] } keys
 */
 export function removeComponentByKeys(treeData,keys) {
  for (let i = treeData.length; i > 0; i--){
    if (keys.includes(treeData[i - 1].key)){
      treeData.splice(i - 1,1)
    } else {
      if (treeData[i - 1].props.list){
        treeData[i - 1].props.list.forEach(item => {
          item.children && removeComponentByKeys(item.children,keys)
        })
      }
    }
  }
}

/**
 * 更新组件id
 * @param { string } id
 * @returns
 */
export function updateComponentKey(id){
  return `${id}${(Math.random() * 1000000).toFixed(0)}`
}


/**
 * 元素相对于Canvas的offset
 * @param {*} el
 * @returns
 */
export function getOffsetByCanvas (el) {
  let offsetTop = 0
  let offsetLeft = 0
  while (el && el.id !== canvasId) {
    offsetTop += el.offsetTop
    offsetLeft += el.offsetLeft
    el = el.offsetParent
  }
  return {
    offsetTop,
    offsetLeft
  }
}

/**
 * 根据key获取其父组件
 * @param { Component[] } list
 * @param { Key } key
 * @returns
 */
export function getComponentParentByKey(list, key){
  let parent
  const each = (list) => {
    for (let i = 0; i < list.length; i++){
      const item = list[i]
      if (item.props.list?.length > 0){
        for (let j = 0; j < item.props.list.length; j++){
          const tab = item.props.list[j]
          const selectComponent = tab.children.find(component => component.key === key)
          if (selectComponent){
            parent = item
            break
          }
          else {
            each(tab.children)
          }
        }
      }
    }
  }

  each(list)
  // for(let i = 0;i<list.length;i++){
  //   const item = list[i]
  //   if(item.props.list?.length > 0){
  //     for(let j = 0;j<item.props.list.length;j++){
  //       const tab = item.props.list[j]
  //       const selectComponent = tab.children.find(component => component.key === key)
  //       if(selectComponent){
  //         return item
  //       }
  //       else {
  //         getComponentParentByKey(tab.children)
  //       }
  //     }

  //   }
  // }
  return parent
}
/**
 * 根据key获取组件在父组件中的index和children,如果没有children则返回自身
 * @param { Component[] } list
 * @param { Key } key
 * @param { Component[] } rootList
 * @returns
 */
 export function getParentChildrenByKey(list, key, rootList){
  const parentComponent = getComponentParentByKey(list, key)
  if (!rootList){
    rootList = list
  }
  let index
  let parent
  if (parentComponent){
    // 说明是里层元素
    parent = getComponentChildren(parentComponent)
    index = parent.findIndex(item => item.key === key)
  }
  else {
    // 说明父元素是canvas
    index = rootList.findIndex(item => item.key === key)
    parent = rootList
  }
  return {
    parent,
    index
  }
}
/**
 * 获取组件的children
 * @param { Component } component
 * @returns
 */
export function getComponentChildren(component){
  const {
    list,
    value
  } = component.props
  if (list && list.length > 0){
    const activeTab = list.find(item => item.value === value)
    return activeTab.children
  }
  else {
    return null
  }
}

/**
 * 修改selectedComponent
 * @param {1 | 2} type 修改类型,1: 修改,2: 清空
 * @param {{ data: Component }} option 修改的数据
 */
export function setSelectedComponent(type, option = {}){
  const {data} = option
  const defaultData = {
    style: {},
    props: {},
    events: {},
    jump: {
      targetType: "board",
      openType: "target",
      isFilter: false,
      source: undefined,
      target: []
    },
    linkage: {
      source: undefined,
      componentList: [],
    },
  }
  switch (type){
    case 1:
      store.commit("lowCode/setSelectedComponent",data)
      store.commit("lowCode/setMultipleKeys",)
      setMultipleKeys([data.key])
      break
    case 2:
      store.commit("lowCode/setSelectedComponent",{...defaultData})
      break
    default:
      store.commit("lowCode/setSelectedComponent",{...defaultData})
    }
}

/**
 * 设置多选组件的key
 * @param { Key[] } data
 */
export function setMultipleKeys(data = []){
  store.commit("lowCode/setMultipleKeys", data)
}


/**
 * 往历史记录里添加快照
 * @param {*} type
 * @param { { pageSetting: Style, canvasComponentList: Component[] } } data
 */
export function addSnapshot(type, data){
  const {
    canvasComponentList,
    pageSetting
  } = store.state.lowCode
  const updateComponent = () => {
    store.commit('lowCode/addSnapshot', {
      canvasComponentList: data.canvasComponentList,
      pageSetting
    })
  }
  const updatePage = () => {
    store.commit('lowCode/addSnapshot', {
      canvasComponentList,
      pageSetting: data.pageSetting
    })
  }
  const updateAll = () => {
    store.commit('lowCode/addSnapshot', data)
  }
  switch (type){
    case "component":
      updateComponent()
      break
    case "page":
      updatePage()
      break
    case "all":
      updateAll()
      break
    default :
      updateComponent()
  }
}

/**
 * 判断组件的样式(与上一次快照相比)是否发生了变化
 * @param { [] } styleConfig
 * @returns
 */
export function getIsComponentStyleChange(styleConfig){
  const {
    selectedComponent,snapshotList,snapshotIndex,multipleKeys,canvasComponentList
  } = store.state.lowCode
  let isChange = false
  if (multipleKeys.length === 0){
    return false
  }
  const oldSelectComponents = getComponentListByKeys(snapshotList[snapshotIndex].canvasComponentList, multipleKeys)
  const selectComponents = getComponentListByKeys(canvasComponentList, multipleKeys)
  const config = styleConfig || ['width', 'height', 'left', 'top', 'widthUnit', 'heightUnit', 'leftUnit', 'topUnit']
  for (let i = 0; i < oldSelectComponents.length; i++) {
    const item = oldSelectComponents[i]
    const oldStyle = item.style
    const style = selectComponents[i].style
    const bools = config.map(key => {
      return oldStyle[key] === style[key]
    })
    if (bools.indexOf(false) > -1){
      isChange = true
      break
    }
  }
  return isChange
}

/**
 * 将几何属性对象转换为style
 * @param { Style } style
 * @returns
 */
export function getGeometricStyle(style){
  const {
    left,leftUnit,top,topUnit,width,widthUnit,height,heightUnit
  } = style
  return {
    left: left + leftUnit,
    top: top + topUnit,
    width: width + widthUnit,
    height: height + heightUnit,

  }
}

/**
 * 重置画布和历史记录
 */
export function reset(){
  store.commit('lowCode/setCanvasComponentList', [])
  setSelectedComponent()
  setMultipleKeys([])
  store.commit("lowCode/resetSnapshot")
}


/**
 * 保留指定的小数位（直接截取,非四舍五入）
 * @param {*} n
 * @param {*} fixed
 * @returns
 */
export function toFixed(n, fixed) {
  return ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed)
}
